#pragma once
#include "tcpLog.hpp"
#include "Task.hpp"
#include "ThreadPool.hpp"
#include "protocol.hpp"
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <cstdlib>
#include <cstring>
#include <strings.h>
#include <cstdio>
#define NUM 1024
enum
{
    USAGE_ERR = 1,
    SOCKET_ERR,
    BIND_ERR,
    LISTEN_ERR,
    FORK_ERR,
    WAIT_ERR
};
namespace Server
{


    void serverIo(int sockfd, handler_t handler)
    {
        std::string inbuffer;
        while (true)
        {
            //1.读取 "context_len"\r\n"context"\r\n
            //1.1读取一个完整的报文
            std::string req_package;
            if(!recvPackage(sockfd, inbuffer, &req_package)) break;

            std::cout << "请求去掉报头之前: \n" << req_package << std::endl;
            //1.2将报文去掉包头
            std::string req_str;
            deLenth(req_package, req_str);
            std::cout << "请求去掉报头之后: \n" << req_str << std::endl;


            //2.对请求Request反序列化
            Request req;
            req.deserialize(req_str);

            //3.计算机处理Request  //业务逻辑
            //得到一个响应结构体Response
            Response resp;
            handler(req, resp);

            //4.对响应结构体Response序列化
            std::string resp_str;
            resp.serialize(&resp_str);
            std::cout << "响应添加报头之前: \n" << resp_str << std::endl;


            //5.最后发送响应
            //5.1对响应添加报头
            std::string sendmes;
            enLenth(resp_str, sendmes);
            std::cout << "响应添加报头之后: \n" << sendmes << std::endl;
            //5.2正式发送响应报文
            send(sockfd, sendmes.c_str(), sendmes.size(), 0);
        }

        close(sockfd);
    }
    using namespace std;
    class TcpServer;
    class ServerThreadData
    {
    public:
        ServerThreadData(TcpServer *self, int sock)
            : _self(self), _sock(sock)
        {
        }

    public:
        TcpServer *_self;
        int _sock;
    };
    class TcpServer
    {
        static const int gbacklog = 5;

    public:
        TcpServer(const uint16_t port, const handler_t handler)
            : _port(port)
            ,_listensock(-1)
            ,_handler(handler)
        {
        }
        void initServer()
        {
            // 1.创建socket套接字对象
            _listensock = socket(AF_INET, SOCK_STREAM, 0);
            if (_listensock == -1)
            {
                logMessage(FATAL, "listen socket error");
                exit(SOCKET_ERR);
            }
            logMessage(NORMAL, "listen socket success sockfd: %d", _listensock);

            // 2.绑定ip和端口
            struct sockaddr_in local;
            bzero(&local, sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            local.sin_addr.s_addr = INADDR_ANY;
            if (bind(_listensock, (struct sockaddr *)&local, sizeof(local)) != 0)
            {
                logMessage(FATAL, "bind error");
                exit(BIND_ERR);
            }
            logMessage(NORMAL, "bind success");

            // 3.设置socket为监听状态
            if (listen(_listensock, gbacklog) < 0)
            {
                logMessage(FATAL, "listen error");
                exit(LISTEN_ERR);
            }
            logMessage(NORMAL, "listen success");

            // version 3 多进程 信号忽略子进程的退出，让os回收子进程资源
            // signal(SIGCHLD, SIG_IGN);
        }
        void start()
        {
            // 4.初始化线程池
            ThreadPool<Task>::GetInstance()->run();
            logMessage(DEBUG, "create ThreadPool success");
            while (1)
            {
                // 接受远端连接
                struct sockaddr_in client;
                socklen_t len = sizeof(client);
                int sockfd = accept(_listensock, (struct sockaddr *)&client, &len);
                if (sockfd == -1)
                {
                    logMessage(ERROR, "accept error");
                    continue;
                }
                logMessage(NORMAL, "accept a new link success, get new sock: %d", sockfd);

                

                // 线程池技术
                ThreadPool<Task>::GetInstance()->push(Task(sockfd, _handler, serverIo));
            }
        }

        ~TcpServer()
        {
        }

    private:
        int _listensock; // 不是用来通信的，是用来监听链接到来，获取新链接的

        uint16_t _port;
        handler_t _handler;

    };
}
